<?php
/**
 * Lớp hỗ trợ hiển thị HTML cho view
 * @author Mr.UBKey
 * Cập nhật select
 */
require_once 'XPHP/Html/Base.php';
require_once 'XPHP/String.php';

class XPHP_Html
{
	/**
	 * Model của hệ thống
	 * @var XPHP_Model
	 */
	protected $_model;
	
	/**
	 * Router của hệ thống
	 * @var XPHP_Router
	 */
	protected $_router;
	
	/**
	 * Mã javascript
	 * @var bool
	 */
	private $_script = "";
	
	/**
	 * Tên form
	 */
	private $_formName;
	
	/**
	 * Model của hệ thống
	 * @param XPHP_Router $router
	 * @param XPHP_Model $model
	 */
	public function __construct($router=NULL, $model=NULL)
	{
		if($router !== NULL)
			$this->_router = $router;
		if($model !== NULL)
		{
			$this->_model = $model;
		}
	}
	
	public function beginForm($name, $attrs=NULL)
	{
		if(!isset($attrs["method"]))
			$attrs["method"] = "post";
		if(!isset($attrs["id"]))
			$attrs["id"] = $name;
		//Gán tên form
		$this->_formName = $attrs["id"];
		$attr = XPHP_Html_Base::htmlAttributes($attrs);
	
		echo "<form name='$name' $attr>";
	}
	
	public function endForm()
	{
		echo "</form>";
	}
	
	/**
	 * Tạo label
	 * @param string $text Text hiển thị trong label
	 * @param array $attrs Mảng các attributes name => value
	 */
	public function label($text, $attrs=NULL)
	{
		if($attrs !== NULL && is_array($attrs))
		{
			$attr = XPHP_Html_Base::htmlAttributes($attrs);
			$html = "<label $attr>$text</label>";
		}
		else
			$html = "<label>$text</label>";
			
		echo $html;
	}
	
	public function labelFor($property, $attrs=NULL)
	{
		try {
			$attrs["for"] = $property;
			$attributes = XPHP_Attribute::PropertyAttributes($this->_model, $property)->attributes;
			if(isset($attributes["label"]))
				$this->label($attributes["label"], $attrs);
			else 
				$this->label($property, $attrs);
		}
		catch (XPHP_Exception $ex){
			throw new XPHP_Exception("Không tìm thấy thuộc tính $property trong " . get_class($this->_model));
		}
	}
	
	public function textbox($name, $value=NULL, $attrs=NULL)
	{
		//Nếu truyền vào giá trị
		if($value !== NULL)
			$attrs["value"] = $value;
		//Nếu không truyền vào attribute id lấy tên làm id
		if(!isset($attrs["id"]))
			$attrs["id"] = $name;
		if($attrs !== NULL && is_array($attrs))
		{
			$attr = XPHP_Html_Base::htmlAttributes($attrs);
			$html = "<input name='$name' type='text' $attr/>";
		}
		else
			$html = "<input name='$name' type='text' />";
			
		echo $html;
	}
	
	public function textboxFor($property, $attrs=NULL)
	{
		try {
			if(!empty($this->_model->$property))
				$attrs["value"] = $this->_model->$property;
			$attributes = XPHP_Attribute::PropertyAttributes($this->_model, $property)->attributes;
			if(isset($attributes["description"]))
				$attrs["title"] = $attributes["description"];
				
			$this->textbox($property, NULL, $attrs);
		}
		catch (XPHP_Exception $ex){
			throw new XPHP_Exception("Không tìm thấy thuộc tính $property trong " . get_class($this->_model));
		}
	}
	
	public function password($name, $value=NULL, $attrs=NULL)
	{
		//Nếu truyền vào giá trị
		if($value !== NULL)
			$attrs["value"] = $value;
		//Nếu không truyền vào attribute id lấy tên làm id
		if(!isset($attrs["id"]))
			$attrs["id"] = $name;
		if($attrs !== NULL && is_array($attrs))
		{
			$attr = XPHP_Html_Base::htmlAttributes($attrs);
			$html = "<input name='$name' type='password' $attr/>";
		}
		else
			$html = "<input name='$name' type='password' />";
			
		echo $html;
	}
	
	public function passwordFor($property, $attrs=NULL)
	{
		try {
			if(!empty($this->_model->$property))
				$attrs["value"] = $this->_model->$property;
			$attributes = XPHP_Attribute::PropertyAttributes($this->_model, $property)->attributes;
			if(isset($attributes["description"]))
				$attrs["title"] = $attributes["description"];
				
			$this->password($property, NULL, $attrs);
		}
		catch (XPHP_Exception $ex){
			throw new XPHP_Exception("Không tìm thấy thuộc tính $property trong " . get_class($this->_model));
		}
	}
	
	public function textarea($name, $value=NULL, $attrs=NULL)
	{
		//Nếu truyền vào giá trị
		if($value !== NULL)
			$attrs["value"] = $value;
		//Nếu không có giá trị truyền vào
		if(!isset($attrs["value"]))
			$attrs["value"] = "";
		//Nếu không truyền vào attribute id lấy tên làm id
		if(!isset($attrs["id"]))
			$attrs["id"] = $name;
		if($attrs !== NULL && is_array($attrs))
		{
			$attr = XPHP_Html_Base::htmlAttributes($attrs);
			$html = "<textarea name='$name' $attr>".$attrs["value"]."</textarea>";
		}
		else
			$html = "<textarea name='$name'>".$attrs["value"]."</textarea>";
			
		echo $html;
	}
	
	public function textareaFor($property, $attrs=NULL)
	{
		try {
			if(!empty($this->_model->$property))
				$attrs["value"] = $this->_model->$property;
			$attributes = XPHP_Attribute::PropertyAttributes($this->_model, $property)->attributes;
			if(isset($attributes["description"]))
				$attrs["title"] = $attributes["description"];
				
			$this->textarea($property, NULL, $attrs);
		}
		catch (XPHP_Exception $ex){
			throw new XPHP_Exception("Không tìm thấy thuộc tính $property trong " . get_class($this->_model));
		}
	}
	
	public function hidden($name, $value=NULL, $attrs=NULL)
	{
		//Nếu truyền vào giá trị
		if($value !== NULL)
			$attrs["value"] = $value;
		//Nếu không truyền vào attribute id lấy tên làm id
		if(!isset($attrs["id"]))
			$attrs["id"] = $name;
		if($attrs !== NULL && is_array($attrs))
		{
			$attr = XPHP_Html_Base::htmlAttributes($attrs);
			$html = "<input name='$name' type='hidden' $attr/>";
		}
		else
			$html = "<input name='$name' type='hidden' />";
			
		echo $html;
	}
	
	public function hiddenFor($property, $attrs=NULL)
	{
		try {
			if(!empty($this->_model->$property))
				$attrs["value"] = $this->_model->$property;
			$attributes = XPHP_Attribute::PropertyAttributes($this->_model, $property)->attributes;
			if(isset($attributes["description"]))
				$attrs["title"] = $attributes["description"];
				
			$this->hidden($property, NULL, $attrs);
		}
		catch (XPHP_Exception $ex){
			throw new XPHP_Exception("Không tìm thấy thuộc tính $property trong " . get_class($this->_model));
		}
	}
	
	public function checkbox($name, $value=NULL, $attrs=NULL)
	{
		//Nếu truyền vào giá trị
		if($value !== NULL)
		{
			if(is_bool($value))
				$attrs["checked"] = "checked";
			else 	
				$attrs["value"] = $value;
		}
		//Nếu không truyền giá trị thì giá trị của value là true
		$attrs["value"] = "true";
		//Nếu không truyền vào attribute id lấy tên làm id
		if(!isset($attrs["id"]))
			$attrs["id"] = $name;
		if($attrs !== NULL && is_array($attrs))
		{
			$attr = XPHP_Html_Base::htmlAttributes($attrs);
			$html = "<input type='checkbox' name='$name' $attr />";
		}
		else
			$html = "<input type='checkbox' name='$name' />";
			
		echo $html;
	}
	
	public function checkboxFor($property, $attrs=NULL)
	{
		try {
			$value = NULL;
			if(!empty($this->_model->$property))
				$value = $this->_model->$property;				
			//Nếu value = true thì check
			if($value || $value == "true")
				$attrs["checked"] = "checked";
			//Lấy attribute	
			$attributes = XPHP_Attribute::PropertyAttributes($this->_model, $property)->attributes;
			if(isset($attributes["description"]))
				$attrs["title"] = $attributes["description"];
			//Gọi phương thức checkbox
			$this->checkbox($property, $value, $attrs);
		}
		catch (XPHP_Exception $ex){
			throw new XPHP_Exception("Không tìm thấy thuộc tính $property trong " . get_class($this->_model));
		}
	}
	
	public function radio()
	{}
	
	public function radioFor()
	{}
	
	public function select($name, $arrOptions, $value=NULL, $valueID, $nameID, $attrs=NULL)
	{
		if ($attrs !==NULL)
		{
			$attr = XPHP_Html_Base::htmlAttributes($attrs);
			$html = "<select name='$name' $attr />";
		}
		else
		{
			$html = "<select name='$name' id='$name'/>";
		}
		foreach ($arrOptions as $key=>$option)
		{
			//Nếu không có valueID và nameID
			if ($valueID == NULL || $nameID == NULL)
				if ($value == $option)
					$html .= '<option value="'.$key.'" selected="selected">'.$option.'</option>';
				else 
					$html .= '<option value="'.$key.'">'.$option.'</option>';
			else 
				if ($value == $option[$valueID])
					$html .= '<option value="'.$option[$valueID].'" selected="selected">'.$option[$nameID].'</option>';
				else 
					$html .= '<option value="'.$option[$valueID].'">'.$option[$nameID].'</option>';
		}
		
		$html .= "</select>";
		
		echo $html;
	}
	
	public function selectFor($property, $arrOptions, $valueID=NULL, $nameID=NULL, $attrs=NULL)
	{
		try {
			$value = NULL;
			if(!empty($this->_model->$property))
				$value = $this->_model->$property;
			$attributes = XPHP_Attribute::PropertyAttributes($this->_model, $property)->attributes;
			if(isset($attributes["description"]))
				$attrs["title"] = $attributes["description"];
				
			$this->select($property, $arrOptions, $value, $valueID, $nameID, $attrs);
		}
		catch (XPHP_Exception $ex){
			throw new XPHP_Exception("Không tìm thấy thuộc tính $property trong " . get_class($this->_model));
		}
	}
	
	public function submit($name=NULL, $value=NULL, $attrs=NULL)
	{
		//Nếu truyền vào tên
		if($name !== NULL)
			$attrs["name"] = $name;
		//Nếu truyền vào giá trị
		if($value !== NULL)
			$attrs["value"] = $value;
		//Nếu không truyền vào attribute id lấy tên làm id
		if(!isset($attrs["id"]) && isset($attrs["name"]))
			$attrs["id"] = $attrs["name"];
		if($attrs !== NULL && is_array($attrs))
		{
			$attr = XPHP_Html_Base::htmlAttributes($attrs);
			$html = "<input name='$name' type='submit' $attr/>";
		}
		else
			$html = "<input name='$name' type='submit' />";
			
		echo $html;
	}
	/**
	 * Button reset
	 * @param string $name
	 * @param string $value
	 * @param array $attrs
	 */
	public function reset($name=NULL, $value=NULL, $attrs=NULL)
	{
		//Nếu truyền vào tên
		if($name !== NULL)
			$attrs["name"] = $name;
		//Nếu truyền vào giá trị
		if($value !== NULL)
			$attrs["value"] = $value;
		//Nếu không truyền vào attribute id lấy tên làm id
		if(!isset($attrs["id"]) && isset($attrs["name"]))
			$attrs["id"] = $attrs["name"];
		if($attrs !== NULL && is_array($attrs))
		{
			$attr = XPHP_Html_Base::htmlAttributes($attrs);
			$html = "<input type='reset' $attr/>";
		}
		else
			$html = "<input type='reset' />";
			
		echo $html;
	}
	/**
	 * Cho phép valid phía client
	 */
	public function enableClientSideValidation()
	{
		require_once 'XPHP/Html/Validation.php';
		$validation = new XPHP_Html_Validation($this->_model);
		$validation->setFormName($this->_formName);
		$this->_script .= $validation->getScript();
	}
	
	public function validationMessageFor($property, $attrs=NULL)
	{
		$messages = $this->_model->getErrorMessage();
		if($messages != NULL)
		{
			$attrs["for"] = $property;
			$errorMess = "";
			if(isset($messages[$property]) && sizeof($messages[$property]) > 0)
			{
				sort($messages[$property]);
				$errorMess = $messages[$property][0];
			}	
			if(!empty($errorMess))
			{
				$this->label($errorMess, $attrs);
			}
		}
	}
	
	/**
	 * Hiển thị script tự động render
	 * 
	 */
	public function scriptRegistrar()
	{
		echo $this->_script;
	}
	
	/**
	 * Load CSS
	 * @param string $path
	 * @throws XPHP_Exception
	 */
	public function loadCSS($path)
	{
		if(is_file($path))
			echo '<link href="' . XPHP_Url::getAbsoluteUrl() . '/' . $path . '" rel="stylesheet" type="text/css" />';
		else
		{
			require_once 'XPHP/Exception.php';
			throw new XPHP_Exception("Không tìm thấy tệp tin css tại " . XPHP_Url::getAbsoluteUrl() . '/' . $path);
		}	
	}
	
	/**
	 * Load Javascript
	 * @param string $path
	 * @throws XPHP_Exception
	 */
	public function loadJS($path)
	{
		if(is_file($path))
			echo '<script language="javascript" src="' . XPHP_Url::getAbsoluteUrl() . '/' . $path . '" type="text/javascript"></script>';
		else
		{
			require_once 'XPHP/Exception.php';
			throw new XPHP_Exception("Không tìm thấy tệp tin javascript tại " . XPHP_Url::getAbsoluteUrl() . '/' . $path);	
		}
	}
	
	/**
	 * Overload method action.
	 */
	function __call($method_name, $arguments)
	{
    	//we inspect number of arguments
	    if($method_name == "renderAction" && count($arguments) == 1)
	    {
	    	return $this->renderAction1($arguments[0]);
	    }
	    else if($method_name == "renderAction" && count($arguments) == 2 && is_string($arguments[1]))
	    {
	    	return $this->renderAction2($arguments[0], $arguments[1]);
	    }
		else if($method_name == "renderAction" && count($arguments) == 2 && is_array($arguments[1]))
	    {
	    	return $this->renderAction5($arguments[0], $arguments[1]);
	    }
	    else if($method_name == "renderAction" && count($arguments) == 3 && is_string($arguments[2]))
	    {
	    	return $this->renderAction3($arguments[0], $arguments[1], $arguments[2]);
	    }
		else if($method_name == "renderAction" && count($arguments) == 3 && is_array($arguments[2]))
	    {
	    	return $this->renderAction6($arguments[0], $arguments[1], $arguments[2]);
	    }
		else if($method_name == "renderAction" && count($arguments) == 4)
	    {
	    	return $this->renderAction4($arguments[0], $arguments[1], $arguments[2], $arguments[3]);
	    }
	}
	
  	function renderAction1($action)
  	{
    	$router = $this->_router->getInstant();
    	$router->setAction($action);
    	//Execute request
    	$frontController = new XPHP_Controller_Front();
		$frontController->setRouter($router);
		$frontController->dispatch(); 
  	}

  	function renderAction2($action, $controller)
  	{
    	$router = $this->_router->getInstant();
    	$router->setAction($action);
    	$router->setController($controller);
    	//Execute request
    	$frontController = new XPHP_Controller_Front();
		$frontController->setRouter($router);
		$frontController->dispatch(); 
  	}

  	function renderAction3($action, $controller, $area)
  	{
    	$router = $this->_router->getInstant();
    	$router->setAction($action);
    	$router->setController($controller);
    	$router->setArea($area);
    	//Execute request
    	$frontController = new XPHP_Controller_Front();
		$frontController->setRouter($router);
		$frontController->dispatch(); 
  	}
	
  	function renderAction4($action, $controller, $area, $args)
  	{
    	$router = $this->_router->getInstant();
    	$router->setAction($action);
    	$router->setController($controller);
    	$router->setArea($area);
    	$router->setArgs($args, true);
    	//Execute request
    	$frontController = new XPHP_Controller_Front();
		$frontController->setRouter($router);
		$frontController->dispatch(); 
  	}
  	
	function renderAction5($action, $args)
  	{
    	$router = $this->_router->getInstant();
    	$router->setAction($action);
    	$router->setArgs($args, true);
    	//Execute request
    	$frontController = new XPHP_Controller_Front();
		$frontController->setRouter($router);
		$frontController->dispatch(); 
  	}
  	
	function renderAction6($action, $controller, $args)
  	{
    	$router = $this->_router->getInstant();
    	$router->setAction($action);
    	$router->setController($controller);
    	$router->setArgs($args, true);
    	//Execute request
    	$frontController = new XPHP_Controller_Front();
		$frontController->setRouter($router);
		$frontController->dispatch(); 
  	}
  	
  	public function stringEncode($html)
  	{
  		return XPHP_String::HtmlStringEncode($html);
  	}

  	public function stringDecode($html)
  	{
  		return XPHP_String::HtmlStringDecode($html);
  	}
  	
  	public function encode($html)
  	{
  		return XPHP_String::HtmlEncode($html);
  	}
  	
  	public function decode($html)
  	{
  		return XPHP_String::HtmlDecode($html);
  	}
  	
  	public function raw($html_stringencoded)
  	{
  		echo $this->stringDecode($html_stringencoded);
  	}
}